package net.wicp.tams.common.binlog.self;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFileFilter;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;

import net.wicp.tams.common.Conf;
import net.wicp.tams.common.apiext.IOUtil;
import net.wicp.tams.common.binlog.self.bean.Host;
import net.wicp.tams.common.binlog.self.constant.Checksum;
import net.wicp.tams.common.binlog.self.reader.BinglogReadByFile;
import net.wicp.tams.common.binlog.self.sender.ISender;
import net.wicp.tams.common.constant.PathType;
import net.wicp.tams.common.thread.threadlocal.PerThreadValue;
import net.wicp.tams.common.thread.threadlocal.PerthreadManager;

public class DumpByFile {

	private final String dirPath;
	private final String prefix;
	private final String[] binlogFiles;
	private final ISender sender;
	private final String dbPattern;
	private final String tbPattern;
	private final Checksum checksum;
	private ICallBack callBack;
	private int min = -1;
	private int max = -1;
	private final Properties cols = new Properties();
	private String beginGtid;
	private String endGtid;

	public void setCallBack(ICallBack callBack) {
		this.callBack = callBack;
	}

	public DumpByFile(String dirPath, String prefix, String dbPattern, String tbPattern, Checksum checksum,
			ISender sender) {
		this.dirPath = dirPath;
		this.prefix = prefix;
		this.binlogFiles = null;
		this.sender = sender;
		this.dbPattern = dbPattern;
		this.tbPattern = tbPattern;
		this.checksum = checksum;
	}

	public DumpByFile(String dirPath, String dbPattern, String tbPattern, Checksum checksum, ISender sender,
			String... binlogFiles) {
		this.dirPath = dirPath;
		this.prefix = null;
		this.binlogFiles = binlogFiles;
		this.sender = sender;
		this.dbPattern = dbPattern;
		this.tbPattern = tbPattern;
		this.checksum = checksum;
	}

	public static interface ICallBack {
		public void doCallBack(File file);
	}

	public void readFile(long beginPos) throws IOException {
		readFile(beginPos, -1);
	}

	public void readFile() throws IOException {
		readFile(4, -1);
	}

	public void readFile(long beginPos, long endPos) throws IOException {
		Validate.notNull(dirPath);
		Validate.notNull(sender);
		if (cols.isEmpty()) {
			String colnamepropfile = PathType.getPath(Conf.get("zorro.binlog.colnamepropfile"));
			// Properties cols = IOUtil.fileToProperties(new
			// File(colnamepropfile));//
			// IOUtil.fileToProperties(colnamepropfile,
			// DumpByFile.class);
			cols.load(new FileReader(new File(colnamepropfile)));
		}

		if (cols == null || cols.size() == 0) {
			throw new IllegalAccessError("没有列属性");
		}

		List<File> parserFiles = new ArrayList<>();

		if (prefix != null) {
			Collection<File> filelist = FileUtils.listFiles(new File(dirPath), new IOFileFilter() {
				@Override
				public boolean accept(File dir, String name) {
					return true;
				}

				@Override
				public boolean accept(File file) {
					String filename = file.getName();
					boolean check = filename.startsWith(prefix + ".") && !filename.endsWith("index");
					if (!check) {
						return false;
					}
					if (min >= 0 || max >= 0) {
						int index = Integer.parseInt(filename.substring(filename.indexOf(".") + 1));
						if (min >= 0 && index < min) {
							return false;
						}
						if (max >= 0 && index > max) {
							return false;
						}
					}
					return true;
				}
			}, FileFileFilter.FILE);// TrueFileFilter.INSTANCE
			parserFiles.addAll(filelist);
		} else if (ArrayUtils.isNotEmpty(binlogFiles)) {
			for (String fileName : binlogFiles) {
				parserFiles.add(new File(IOUtil.mergeFolderAndFilePath(dirPath, fileName)));
			}
		}

		for (File file : parserFiles) {
			BinglogReadByFile reader = new BinglogReadByFile(file, dbPattern, tbPattern, checksum, sender);
			PerThreadValue<Host> creator = PerthreadManager.getInstance().createValue(Host.preVar);
			Host host = creator.get(new Host());
			host.addCols(cols);
			reader.setEndPos(endPos);
			reader.setBeginGtid(beginGtid);
			reader.setEndGtid(endGtid);
			reader.read(beginPos);
			reader.close();
			PerthreadManager.getInstance().cleanValue(Host.preVar);
			if (callBack != null) {
				callBack.doCallBack(file);
			}
		}
	}

	public int getMin() {
		return min;
	}

	public void setMin(int min) {
		this.min = min;
	}

	public int getMax() {
		return max;
	}

	public void setMax(int max) {
		this.max = max;
	}

	public Properties getCols() {
		return cols;
	}

	public String getBeginGtid() {
		return beginGtid;
	}

	public void setBeginGtid(String beginGtid) {
		this.beginGtid = beginGtid;
	}

	public String getEndGtid() {
		return endGtid;
	}

	public void setEndGtid(String endGtid) {
		this.endGtid = endGtid;
	}
}
